package VerticalPrototypes;

import java.sql.*;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

/**
 * @author Tyler Wood
 */

//Class for retreiving and setting an item's (book) information via the ISBN online database.
//Three-STEP CLASS
    //1. Get book information from outside database and store it in a mapping.
          
    //2. Use a mapping of a book, store the information in a book object.
        //Note: The book class can be stored directly as an object, via RMI, if needed. (>'')> <(''<)

    //3. Put book object, get book information and put into the database using SQL queries.

//This code was spread out over:
//https://github.com/snyamathi/LitHub/blob/dev/LitHub-Android/src/us/lithub/data/Book.java
//https://github.com/snyamathi/LitHub/blob/dev/LitHub-Android/src/us/lithub/data/BookParser.java
//https://github.com/snyamathi/LitHub/blob/dev/LitHub-Android/src/us/lithub/data/ItemLookup.java
//I have refactored it into one class, as a prototype.

public class SetItemInfoByISBN {
    
    //Instance of this class being used.
    private static SetItemInfoByISBN instance = null;

    
    //Book class; holds got book information. We can make a class for DVDs or Games etc etc etc.
    //Complete with getters and setters.
    //Mapper maps to the public static final variables.
    
    public class Book {
        
        public static final String TITLE = "Title";
        public static final String TITLE_LONG = "Title Long";
        public static final String AUTHOR_TEXT = "AuthorsText";
        public static final String PUBLISHER_TEXT = "PublisherText";
        public static final String ISBN = "isbn";
        public static final String SUMMARY = "Summary";
        
        private String title;
        private String title_long;
        private String author;
        private String publisher;
        private String isbn;
        private String summary;

        public Book() {
        }
        
        public String getTitle() {
            return title;
        } 
        
        public String getTitleLong() {
            return title_long;
        }   
        
         public String getAuthorText() {
            return author;
        }   
        
        public String getPublisherText() {
            return publisher;
        }
        
        public String getISBN() {
            return isbn;
        }
        
        public String getSummary() {
            return summary;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public void setTitleLong(String title_long) {
            this.title_long = title_long;
        }

        public void setAuthorText(String author) {
            this.author = author;
        }

        public void setPublisherText(String publisher) {
            this.publisher = publisher;
        }

        public void setISBN(String isbn) {
            this.isbn = isbn;
        }

        public void setSummary(String summary) {
            this.summary = summary;
        }                    
    }
    
    //Simplified method call for getting information by ISBN
    public static Map<String, String> getBookAttributesFromIsbn(String isbn) {
        return getBookAttributesFromUpc(isbn);
    }
    
    //Map Helper Function.
    public static Map<String, String> getBookAttributesFromUpc(String upc) {

            try {
                    final URL url = new URL("http://isbndb.com/api/books.xml?access_key=MIIRXTQX&index1=isbn&value1=" + upc);
                    final SAXParserFactory spf = SAXParserFactory.newInstance();
                    final SAXParser sp = spf.newSAXParser();	
                    final XMLReader xr = sp.getXMLReader();	
                    final IsbnDbHandler handler = new IsbnDbHandler();
                    xr.setContentHandler(handler);
                    xr.parse(new InputSource(url.openStream()));
                    return handler.getAttributes();
            } catch (MalformedURLException e) {
                    System.out.println(e.getMessage());
            } catch (SAXException e) {
                    System.out.println(e.getMessage());
            } catch (ParserConfigurationException e) {
                    System.out.println(e.getMessage());
            } catch (IOException e) {
                    System.out.println(e.getMessage());
            }

            return null;
    }
    
    //Handler enhancements.
    private static class IsbnDbHandler extends DefaultHandler {

            private Map<String, String> map;

            private boolean Title;
            private boolean TitleLong;
            private boolean AuthorsText;
            private boolean PublisherText;
            private boolean Summary;

            public IsbnDbHandler() {
                    map = new HashMap<String, String>();
            }

            public Map<String, String> getAttributes() {
                    return map;
            }

            @Override
            public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
                    if (localName.equals("BookData")) {
                            String isbn = atts.getValue(Book.ISBN);
                            map.put(Book.ISBN, isbn); 
                    } else if (localName.equals(Book.TITLE)) {
                            Title = true;
                    } else if (localName.equals(Book.TITLE_LONG)) {
                            TitleLong = true;
                    } else if (localName.equals(Book.AUTHOR_TEXT)) {
                            AuthorsText = true;
                    } else if (localName.equals(Book.PUBLISHER_TEXT)) {
                            PublisherText = true;
                    } else if (localName.equals(Book.SUMMARY)) {
                            Summary = true;
                    }
            }

            @Override
            public void characters(char ch[], int start, int length) throws SAXException {
                    if (Title) {
                            map.put(Book.TITLE, new String(ch, start, length));
                            Title = false;
                    } else if (TitleLong) {
                            map.put(Book.TITLE_LONG, new String(ch, start, length));
                            TitleLong = false;
                    } else if (AuthorsText) {
                            map.put(Book.AUTHOR_TEXT, new String(ch, start, length).replaceAll(",", ""));
                            AuthorsText = false;
                    } else if (PublisherText) {
                            map.put(Book.PUBLISHER_TEXT, new String(ch, start, length));
                            PublisherText = false;
                    } else if (Summary) {
                            map.put(Book.SUMMARY, new String (ch, start, length));
                            Summary = false;
                    }
            }
    }
    
    //Main class.
    public SetItemInfoByISBN()
    {
        Connection con = null;
        Statement st = null;
        ResultSet rs = null;

        //Hardcoded Lithub database location.
        String url = "snyamathi.dyndns.org:37965";
        String user = "root";
        String password = "baconatmidnight";
        
        //Hardcoded prototype book ISBN to get information of.
        String isbn13 = "9781615689750"; //Grabbed a book ISBN.
        
        //Get a mapping of all book information.
        Map<String, String> bookMap = getBookAttributesFromIsbn(isbn13);

        //Create book to hold the book information.
        Book aBook = new Book();
        
        //Map the information to the book.
        aBook.setTitle(bookMap.get(Book.TITLE));
        aBook.setTitleLong(bookMap.get(Book.TITLE_LONG));
        aBook.setAuthorText(bookMap.get(Book.AUTHOR_TEXT));
        aBook.setPublisherText(bookMap.get(Book.PUBLISHER_TEXT));
        aBook.setISBN(bookMap.get(Book.ISBN));
        aBook.setSummary(bookMap.get(Book.SUMMARY));

        //Now let's try to add the book to the database, since we now have a sanitized book information class.
        try {
            //Connect to the LitHub database.
            con = DriverManager.getConnection(url, user, password);
            st = con.createStatement();

            //Let's add the book to the database, shall we?
            
            //INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, value2, value3,...)
            if(rs == (st.executeQuery("INSERT INTO items (itemName, itemNameLong, itemAuthor, itemPublisher, itemISBN, itemSummary...) "
                    + "VALUES (" + aBook.getTitle() + ", " + aBook.getTitleLong() + ", "  + aBook.getAuthorText() 
                    + ", " + aBook.getPublisherText() + ", "  + aBook.getISBN() + ", "  + aBook.getSummary() + ")")))
                    
            { /*Success; inserted properly */ }
            else{ /*Not success.*/ }

            //Prints out results.
            if (rs.next()) {
                System.out.println(rs);
            }

        } catch (SQLException ex) {
                //Something happens.
        } finally {
            //Close connections safely.
            try {
                if (rs != null) {
                    rs.close();
                }
                if (st != null) {
                    st.close();
                }
                if (con != null) {
                    con.close();
                }

            } catch (SQLException ex) {
                    //Something happens.
            }
        }
    }
    
    //Execute the getting of an email by username.
    public static SetItemInfoByISBN user_SetItemInfoByISBN()
    {
        if(instance == null)
            instance = new SetItemInfoByISBN();
        return instance;
    }  
}